/**
 * 
 */

var BusTrack = {
  map: null,
  geocoder: null,
  directionService: null,
  
  busmarker: null,
  pickupmarker: null,
  
  
  infowindow: null,
  directionRenderer: null,
  
  busPosition: null,
  pickupPoint: null,
  
  polyOptions: {
		    strokeColor: '#550000',
		    strokeOpacity: 1.0,
		    strokeWeight: 3
  },
  polyLine: null,
  
  directionRendererOptions: {
	  draggable: false,
	  /*suppressMarkers: true,
	  suppressInfoWindows: true,*/
	  polylineOptions: {
		    strokeColor: '#002277',
		    strokeOpacity: 1.0,
		    strokeWeight: 3
	  } 
  },
  
  lastMapViewChangeByUser: null,
  
  routeData: null,
  
  mapInitialize: function() {
	this.geocoder = new google.maps.Geocoder();
	this.directionService = new google.maps.DirectionsService();
	
	this.infowindow = new google.maps.InfoWindow();
	if (!this.busPosition)
		this.busPosition = new google.maps.LatLng(-34.397, 150.644);
	
    var myOptions = {
      zoom: 16,
      center: this.busPosition,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    this.map = new google.maps.Map(document.getElementById("map_canvas"),
        myOptions);
    google.maps.event.addListener(this.map, 'zoom_changed', $.hitch(this, this.mapZoomChange));
    google.maps.event.addListener(this.map, 'dragend', $.hitch(this, this.mapDragged));
    google.maps.event.addListener(this.map, 'drag', $.hitch(this, this.mapDragged));
    //google.maps.event.addListener(map, 'click', mapClicked);
    
    this.polyLine = new google.maps.Polyline(this.polyOptions);
    this.polyLine.setMap(this.map);

    this.pickupmarker = new google.maps.Marker({
        map: this.map,
        position: this.busPosition,
        visible: false,
        title: "Your pickup point"
    });
    this.busmarker = new google.maps.Marker({
        map: this.map,
        position: this.busPosition,
        visible: false,
        title: "Bus Location"
    });
    google.maps.event.addListener(this.busmarker, 'click', $.hitch(this, this.busMarkerClicked));
    
	this.directionRenderer = new google.maps.DirectionsRenderer();
  },
  
  setBusPickupPoints: function (data) {
	  var wayPoints = [];
	  var origin = { location: data.bps[0].location };	 
	  var wayPoint = null;
	  var key = null;
	  for(key in data.bps) {
		  if (key == 0 && key == (data.bps.length-1)) continue;
		  wayPoint = {location: data.bps[key].location, stopover: true};
		  wayPoints.push(wayPoint);		  
	  }
	  var request = {
				origin: origin.location,
				destination: data.bps[key].location,
				waypoints: wayPoints,
				travelMode: google.maps.TravelMode.DRIVING,
				optimizeWaypoints: false
			  };	  
	  this.directionService.route(request, $.hitch(this, this.routeIsCalculated));
	  this.setPickupPoint(origin.location);
  },
 
  setPickupPoint: function(locationString) {
	    this.geocoder.geocode( { 'address': locationString}, $.hitch(this, this.gotDecodedPickupPoint));	  
  },

  
  setBusPosition: function(lat, lng) {
	//if (this.busPosition.lat() == lat && this.busPosition.lng() == lng) return;  	  
    this.busPosition = new google.maps.LatLng(lat, lng);
    this.busmarker.setPosition(this.busPosition);
    this.busmarker.setVisible(true);

    ///// Put a condition if the previous position and now is the same...     
    this.polyLine.getPath().push(this.busPosition);
    
    	
    this.calculateDistanceAndTime();           
  },  
  
  
  locationChanged: function(obj) {
	  this.setPickupPoint(obj.item.value);
	  console.log("Pickup location is changed by User");
  },
  
  calculateDistanceAndTime: function() {
	  
	var time = (new Date()).getTime();
	if ((time - this.lastMapViewChangeByUser) > 10000) { //There should be 10 secs gap 
	    if (this.pickupPoint != null) {
	    	this.map.fitBounds(new google.maps.LatLngBounds(this.busPosition, this.pickupPoint));
	    } else
	    	this.map.panTo(this.busPosition);
	}

	if (this.pickupPoint == null) return;
  },

  
  /////////////////////////////// CALL BACKS ///////////////////////////
  gotDecodedPickupPoint: function (results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
          this.pickupPoint = results[0].geometry.location;
          this.pickupmarker.setPosition(this.pickupPoint);
          this.pickupmarker.setVisible(true);
          this.calculateDistanceAndTime();
      } else {
    	  console.log("Geocode was not successful for the following reason: " + status);
      }	  
  },
  
  gotBusPositionAddress: function(results, status) {
      if (status == google.maps.GeocoderStatus.OK) {    	  
	        if (results[0]) {			          
	          this.infowindow.setContent(results[0].formatted_address);
	          this.infowindow.open(this.map, this.busmarker);			          
	        }
	  } else {
	        console.log("Geocoder failed due to: " + status);
	  }	  
  },  
  
  routeIsCalculated: function(data, status) {	  
	  this.directionRendererOptions.directions = data;
	  this.directionRendererOptions.map = this.map;
	  this.directionRenderer.setOptions(this.directionRendererOptions);
	  
	  this.routeData = data;
	  console.debug(data);
  },
  
  /////////////////// Map Call Backs //////////////////
  mapClicked: function(event) {
      codeLatLng(event.latLng.lat(), event.latLng.lng());	  
  },
  
  mapZoomChange: function(event) { 
	  if ( this.map.getZoom() < 14 ) {
  	    this.map.setZoom(14); 
		this.map.setCenter(this.busPosition);
  	  } 
	  console.debug("map zooooooooooooooooooooooooooooooooom is changed");
  },

  mapDragged: function(event) {
	  this.lastMapViewChangeByUser = (new Date()).getTime();
	  console.debug("map is beeeeeeeeeeeeeeeeeeeeeeeeeeeeing dragged");
  },
  
  busMarkerClicked: function(event) {
	  this.geocoder.geocode({'latLng': this.busPosition}, $.hitch(this, this.gotBusPositionAddress));
	  this.findNearestLatLng();
  },
  
  /////////////////////// Logical Functions ///////////////
  findNearestLatLng: function() {
	
	if (this.routeData == null || this.busPosition == null || this.pickupPoint == null) return;  
	  
	var route = this.routeData.routes[0];
	var nearLatLng = null;
	
	var prev2_latLng = null;
	var prev_latLng = null;
	var prev2_dist = 0;
	var prev_dist = 0;
	
	var found_nearest_to_bus = false;
	var found_nearest_to_pickup = false;
	
	
	var calculated_distance = 0;
	var calculated_duration = 0;
	
	for(var legKey in route.legs) {
		var leg = route.legs[legKey];
		if (found_nearest_to_pickup) break;

		//At every way point, we should add atleasr 10 mins of waiting time.. 
		if (found_nearest_to_bus) {
			calculated_duration += 10*60;
		}			
		
		for(var stepKey in leg.steps) {
			var step = leg.steps[stepKey];
			if (found_nearest_to_pickup) break;
			
			if (found_nearest_to_bus) {
				calculated_distance += step.distance.value;
				calculated_duration += step.duration.value;
			}
			
			for(var latLngKey in step.path) {
				var dist = 0;
				if (!found_nearest_to_bus)
					dist = google.maps.geometry.spherical.computeDistanceBetween(this.busPosition, step.path[latLngKey]);
				else
					dist = google.maps.geometry.spherical.computeDistanceBetween(this.pickupPoint, step.path[latLngKey]);
				
				if (prev2_dist > prev_dist && dist > prev_dist) {
					if (found_nearest_to_bus) found_nearest_to_pickup =  true;
					else { 
						found_nearest_to_bus = true;
						prev2_dist = 0;
						prev_dist = 0;
					}
				} else {
					prev2_dist = prev_dist;
					prev_dist = dist;
					
					prev2_latLng = prev_latLng;
					prev_latLng = step.path[latLngKey];
				}									
			}
		}
	}

	console.debug("----------------> distance is:::: ", calculated_distance);
	console.debug("----------------> duration is:::: ", calculated_duration)
  }
}